package com.hh.controller;

import com.hh.component.FilePathBase;
import com.hh.pojo.MessageModel;
import com.hh.pojo.User;
import com.hh.service.UserService;
import com.sun.org.apache.xpath.internal.objects.XNull;
import org.apache.ibatis.annotations.Param;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

@RestController  /*每个方法都不走视图解析器，相当于给每个方法加了 @ResponseBody*/
@RequestMapping("user")
//@CrossOrigin(origins = "http://localhost:8080",maxAge = 3600)//解决跨域访问
//@CrossOrigin(origins = "http://116.62.224.134:8080",maxAge = 3600)//解决跨域访问
public class UserController {

    @Autowired
    private UserService userService;

    /* 根据用户名获取用户信息(不包括密码等敏感数据) */
    @GetMapping("/getSpUserById/{userName}")
    public Map<String, Object> getUserByUname(@PathVariable("userName") String uname){
        return userService.getSPUserByName(uname);
    }


    /**
     * 获取用户的数量信息  包括发帖数、评论数和加入贴吧数
     * @param name 要获取信息的用户名
     * @return 结果map， 除了要求的三个结果数量键值对外（postCount、prCount、barCount），还有获取结果 rs messageModel
     */
    @GetMapping("getCountInfo")
    public Map<String, Object> getUserCountInfo(@RequestParam("uname") String name){
        return userService.getUserCountInfo(name);
    }

    /*获取当前用户  session 中的*/
    @RequestMapping("getUser")
    public User getCurrentUser(HttpServletRequest request, HttpServletResponse response){
        return getCurrentUser(request);
    }

    /*必须在 RequestMapping（或GetMapping等）中设置编码（通过Response对象设置没用），否则当你直接返回字符串到前端的时候，
    * 会出现乱码（我这里表现的是问号）
    * 直接封装成对象以 json的形式给回给前端是不用设置编码的  中文也不会出现乱码*/
    /*
    触发场景： 一般是没有权限等，被拦截器拦截，然后跳转到该控制器进行处理
    * 处理没有权限的问题  根据情况（未登录或不是管理员等等）跳转(重定向)到前端的 errorPage
    * 参数通过地址栏拼接传递 前端一样可以接收（不过要注意一下中文的转码）
    * */
//    @RequestMapping(value = "handleRight", produces = "text/html;charset=utf-8")
    @RequestMapping(value = "handleRight") //这里是进行重定向，不是直接返回字符串，所以不设置编码也可以
    public String handleLoginRight(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        // 以下的设置 中文乱码问题 讲道理 在 servlet 中是 可以的，但是在这里没有用，可能是前后端分离的原因
        // 浏览器里看响应头 里 的 Content-Type, text/html;charset=utf-8   他总不是 utf-8 编码，总是一个默认的 ISO 什么的
//        response.setCharacterEncoding("utf-8");
//        response.setContentType("text/html;charset=utf-8");
//        response.setHeader("Content-Type", "text/html;charset=utf-8");

        String status = (String) request.getAttribute("status");
        HashMap<String, String> params = new HashMap<>(); /* 前端errorPage 地址栏添加的参数*/

        //地址栏参数填充
        params.put("errSection",  URLEncoder.encode("后台管理","utf8"));  /*无论结果是什么，都属于后台管理模块*/
        switch (status){
            case "noLogin":
                params.put("errDesc", URLEncoder.encode("当前未登录，请先登录！","utf8"));
                params.put("redctType", "0");  /*0表示 显示登录按钮*/
                break;
            case "notAdmin":
                params.put("errDesc", URLEncoder.encode("权限不足，请先申请管理员权限！","utf8"));
                params.put("redctType", "1");  /*1表示 显示返回首页按钮*/
                break;
            default:
                params.put("errDesc", URLEncoder.encode("Error: 服务器状态校验错误！！！","utf8"));
                params.put("redctType", "1");
        }

        // 跳转到前端错误页面
        request.setAttribute("params", params);
        request.getRequestDispatcher("/user/toErrorPage").forward(request, response);
//        System.out.println("请求转发后面。。。。");  // 请求转发后的代码也会执行
        return null;
    };

    /**
     * 重定向到错误页面
     * @param request 里面必须携带一个 params 参数 Map<String, String>
     *                errSection 错误模块（标题）
     *                errDesc（具体描述）
     *                redctType（0显示登录按钮  1显示返回首页按钮）
     * @param response  重定向响应头
     * @return null
     * @throws IOException  重定向异常
     */
    @RequestMapping(value = "toErrorPage") //这里是进行重定向，不是直接返回字符串，所以不设置编码也可以
    public String toErrorPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 以下的设置 中文乱码问题 讲道理 在 servlet 中是 可以的，但是在这里没有用，可能是前后端分离的原因
        // 浏览器里看响应头 里 的 Content-Type, text/html;charset=utf-8   他总不是 utf-8 编码，总是一个默认的 ISO 什么的
//        response.setCharacterEncoding("utf-8");
//        response.setContentType("text/html;charset=utf-8");
//        response.setHeader("Content-Type", "text/html;charset=utf-8");

        Map<String, String> params = (Map<String, String>) request.getAttribute("params");
        StringBuilder paramStr = new StringBuilder("?"); /* 拼接后的 完整的 地址栏添加的参数 */
        String api = "/errorPage"; //前端端口下的 路径
        String url = FilePathBase.frontEndBaseUrl + api;  /*要重定向到的前端错误地址*/

        //url 拼接 及重定向跳转
        for (String s : params.keySet()) {
            paramStr.append(s);
            paramStr.append("=");
            paramStr.append(params.get(s));
            paramStr.append("&");
        }
        /*如果最后一个字符是 & 则将其删除*/
        if(paramStr.charAt(paramStr.length() - 1) == '&'){
            paramStr.deleteCharAt(paramStr.length() - 1); //删除最后一个字符
        }
        response.sendRedirect(url + paramStr); //重定向可以 精确到http://， 请求转发只能是同源（协议、域名和端口号）
//        System.out.println(url + paramStr);   /*重定向后面的代码  也会走*/
        return null;
    };


    @Test
    public void testStringBuilder(){
        StringBuilder builder = new StringBuilder("123");

        System.out.println(builder.length());
    }
    @Test
    public void testIterator(){
        List<String> list = new ArrayList<>();

        list.add("haohao1");
        list.add("haohao2");
        list.add("haohao3");
        list.add("haohao4");
        list.add("haohao5");

        System.out.println("使用迭代器之前");
        for (String s : list) {
            System.out.print("[" + s + "]");
        }
        System.out.print("\n");

        /**
         *  可以获取一个 collection 的迭代器，
         *  如果在使用迭代器完成迭代之前 原集合发生改变（无论你是直接通过list进行改变还是通过别的迭代器进行更改）的话
         *  再到迭代器那里（next()或者 hasNext() 会报错）
         *  获取集合的迭代器之后，只允许你用本迭代器 对原集合元素进行 修改 remove，其他对list的更改操作都会导致报错
         */
        Iterator<String> iterator = list.iterator();
//        Iterator<String> iterator2 = list.iterator();
//        list.add("haohao8");
        while (iterator.hasNext()){
            String s = iterator.next();
            System.out.println("Iterator迭代器：" + s);
            if (s.equals("haohao3"))
                iterator.remove();
//                list.remove("haohao3");

        }

        Iterator<String> iterator2 = list.iterator();

        while (iterator2.hasNext()){
            String s = iterator2.next();
            System.out.println("Iterator迭代器2：" + s);
//            iterator.remove();
        }

        System.out.println("使用迭代器之后");
        for (String s : list) {
            System.out.print("[" + s + "]");
        }
    }

    /**
     * 检验当前session(与 request对应的session)中是否 已登录（存在user变量，） 当前用户是否却被管理员权限
     * @param request  前端发送的 http请求 request
     * @return 检查结果 MessageModel  605表示未登录， 609表示无权限
     */
    @RequestMapping("checkUserRight")
    public MessageModel checkUserRight(HttpServletRequest request){
        return userService.checkUserRight(request);
    }

    public static User getCurrentUser(HttpServletRequest request){
        HttpSession session = request.getSession();  /*如果当前session不存在，则创建一个新的session*/

        return (User)session.getAttribute("user");
    }

    /*更新一个用户个人资料(暂时不包括邮箱和密码)*/
    /*originalHeadImg  原来的头像文件名  （虽然头像是以用户名命名的，但是不同类型的图片会导致问题  所以此处还是得获取一下）*/
    @RequestMapping("update")
    public Map<String, Object> updateUser(String nickName, @Nullable @RequestParam("file") MultipartFile headImg, String motto, String birthday,
                                   @Nullable @RequestParam("area") String[] area, String intro,String originalHeadImg,
                                          HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
//        String path = request.getServletContext().getRealPath("/static/images/userAvatar/");
        String path = FilePathBase.baseUrl + FilePathBase.userAvatar;  //存放用户头像的地址
        String uname = getCurrentUser(request) == null ? null : getCurrentUser(request).getUname(); // 当前登录用户名、要更新的用户用户名
        MessageModel rs = userService.updateUser(uname, nickName, headImg, motto, birthday, area, intro, originalHeadImg, path, request, response);
        Map<String, Object> map;  //根据用户名查询用户结果
        User user;  //根据用户名查询出来的用户
        Map<String, Object> rsMap = new HashMap<>();

        rsMap.put("rs", rs);
        if (rs.getResult_code() == 200){ //如果更新成功  则更新session中的user 对象
            map = userService.getUserByName(uname);
            if (((MessageModel)map.get("rs")).getResult_code() == 200){  //正常获取到用户
                user = (User)map.get("user");
                user.initArea();  //初始化area数组
                request.getSession().setAttribute("user", user);
                rsMap.put("newHeadImg", user.getHeadImg());  //将现在的headImg放入结果传回前端
            }else {
                rsMap.put("rs", map.get("rs"));  //如果获取用用户出错则直接将出错的rs覆盖原rs
            }
        }
        return rsMap;
//        if (headImg != null){
//            System.out.println("name:" + headImg.getOriginalFilename()); //空字符串
//            System.out.println("size:" + headImg.getSize()); // 0
//        } else
//            System.out.println("file 为null");
//        return new MessageModel(200, "success");
    }

    /*退出登录*/
    @RequestMapping("signOut")
    public MessageModel signOut(HttpServletRequest request){
        MessageModel messageModel = new MessageModel(200, "退出登录成功！");
        HttpSession session = request.getSession(false);  //设置参数false 如果当前session不存在 返回null  而不是新建一个

        if (session == null){  //当前session 不存在
            messageModel.setResult_code(501);
            messageModel.setMsg("退出失败！获取session出错！");
        }else {   // 成功获取到当前session
            session.invalidate();  //使当前session 失效
        }
        return messageModel;
    }

    /*通过用户名和密码(只能通过post方式)  进行登录*/
//    @RequestMapping(value = "login", method = RequestMethod.POST, produces = "application/json")
    @RequestMapping(value = "login", method = RequestMethod.POST)
    @ResponseBody
    public MessageModel login(@RequestParam("name") String uname, @RequestParam("password") String upwd, HttpServletRequest request,
                              HttpServletResponse response){
        Map<String, Object> rsMap = userService.login(uname, upwd);
        MessageModel rsMessageModel = (MessageModel)rsMap.get("rsMessageModel");

        if (rsMessageModel.getResult_code() == 200){ //如果登录成功 则把当前对象存进session
            User user = (User) rsMap.get("user");
            request.getSession().setAttribute("user", user);
            System.out.println("user:" + user);
        }
        return rsMessageModel;
    }

    /* 查询当前用户名是否已被使用 */
    @RequestMapping("userExist")
    public MessageModel checkIfUserExist(@RequestParam("uname") String uname){
        return userService.judgeUserExist(uname);
    }

    /* 注册新账号 */
    @RequestMapping("reg")
    @ResponseBody
    public MessageModel register(String uname, String upwd, String nickName, @Nullable @RequestParam("file") MultipartFile headImg, String motto,
                                 String email, String birthday, @Nullable @RequestParam("area") String[] area, String intro, HttpServletRequest request){
        /*  E:\\IdeaSpringProjects\\forum\\src\\main\\webapp\\static\\images\\userAvatar\\  斜杠带转义  */
        /*注意webapp文件夹的位置 在main 下和 resources 在同一级  这个路径会影响得到的路径，之前得到的时target下的也是这个问题*/
//        String path = request.getServletContext().getRealPath("/static/images/userAvatar/");
        String path = FilePathBase.baseUrl + FilePathBase.userAvatar;  //存放用户头像的地址
        MessageModel rs = userService.insertUser(uname, upwd, nickName, headImg, motto, email, birthday, area, intro, path);
//        MessageModel rs = new MessageModel();
//        System.out.println("received uname： " + uname);
//        System.out.println("received upwd： " + upwd);
//        System.out.println("received nickName： " + nickName);
//        System.out.println("原始文件名：" + headImg.getOriginalFilename());
//        System.out.println("received motto： " + motto);
//        System.out.println("received email： " + email);
//        System.out.println("received birthday： " + birthday);
//        System.out.println("received area： ");
//        for (String s : area) {
//            System.out.println('\t' + "" + s);
//        }
//        System.out.println("received intro： " + intro);
//        return "back from register controller.";
        return rs;
    }

    /*测试 getRealPath*/
    @RequestMapping("testPath")
    public String testRealPath(HttpServletRequest request){
        String path = request.getServletContext().getRealPath("/static/images/userAvatar/");
        return "path:" + path;
    }

    /*测试文件接收*/
    @RequestMapping("testFile")
    @ResponseBody
    public String testFile(@RequestParam("file") MultipartFile file){
        System.out.println("进入控制器");
        System.out.println("原始文件名：" + file.getOriginalFilename());
        return "filePath";
    }

    @GetMapping("testJson")
    public MessageModel tesReturnJson(){
        return new MessageModel(1, "value");
    }

}
